﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
using Microsoft.Win32;

namespace GenerateurMusique
{
    class Individu
    {
        private int[] tbNoteInstrument = new int[17];
        private int tickets;
        private double fitness;
        private byte[] src;
        private byte[] dst;

        /// <summary>
        /// Contruct with no parent
        /// </summary>
        public Individu()
        {
            Random rand = new Random();
            // Ici 16 notes aléatoire entre 16 et 96 (pour éviter certaines notes trop aigues ou trop graves)
            for (int i = 0; i < 16; i++)
            {             
                this.tbNoteInstrument[i] = rand.Next(24, 96);
            }
            Random rand2 = new Random();
            this.tbNoteInstrument[16] = rand2.Next(1, 129);
        }

        /// <summary>
        /// Construct with one parent
        /// </summary>
        /// <param name="_parent1">first Parent</param>
        public Individu(Individu _parent1)
        {
            Random rand = new Random();

            //**Rand pour choisir si aléatoire debut ou fin**//
            if (rand.Next(0, 1) == 0)
            {
                for (int i = 0; i < 8; i++)
                {
                    this.tbNoteInstrument[i] = (rand.Next(24, 96));
                }
                for (int i = 8; i < 17; i++)
                {
                    //1 chance sur 5 de muté
                    if (rand.Next(0, 4) == 3)
                    {
                        this.tbNoteInstrument[i] = (_parent1.tbNoteInstrument[i] - 5 + rand.Next(0, 10));
                    }
                    else
                    {
                        this.tbNoteInstrument[i] = (_parent1.tbNoteInstrument[i]);
                    }
                }
            }
            else
            {
                for (int i = 0; i < 8; i++)
                {
                    //1 chance sur 5 de muté
                    if (rand.Next(0, 4) == 3)
                    {
                        this.tbNoteInstrument[i] = (_parent1.tbNoteInstrument[i] - 5 + rand.Next(0, 10));
                    }
                    else
                    {
                        this.tbNoteInstrument[i] = (_parent1.tbNoteInstrument[i]);
                    }
                }
                for (int i = 8; i < 16; i++)
                {
                    this.tbNoteInstrument[i] = (rand.Next(24, 96));
                }
                Random rand2 = new Random();
                this.tbNoteInstrument[16] = rand2.Next(1, 129);
            }
        }

        /// <summary>
        /// Construc whit two parent
        /// </summary>
        /// <param name="_parent1">first parent</param>
        /// <param name="_parent2">second parent</param>
        public Individu(Individu _parent1, Individu _parent2)
        {
            Random rand = new Random();

            //**Rand pour choisir si parent1 debut ou fin**//
            if (rand.Next(0, 1) == 0)
            {
                for (int i = 0; i < 8; i++)
                {
                    //1 chance sur 5 de muté
                    if (rand.Next(0, 4) == 3)
                    {
                        this.tbNoteInstrument[i] = (_parent1.tbNoteInstrument[i] - 5 + rand.Next(0, 10));
                    }
                    else
                    {
                        this.tbNoteInstrument[i] = (_parent1.tbNoteInstrument[i]);
                    }
                }
                for (int i = 8; i < 17; i++)
                {
                    //1 chance sur 5 de muté
                    if (rand.Next(0, 4) == 3)
                    {
                        this.tbNoteInstrument[i] = (_parent2.tbNoteInstrument[i] - 5 + rand.Next(0, 10));
                    }
                    else
                    {
                        this.tbNoteInstrument[i] = (_parent2.tbNoteInstrument[i]);
                    }
                }
            }
            else
            {
                for (int i = 0; i < 8; i++)
                {
                    //1 chance sur 5 de muté
                    if (rand.Next(0, 4) == 3)
                    {
                        this.tbNoteInstrument[i] = (_parent2.tbNoteInstrument[i] - 5 + rand.Next(0, 10));
                    }
                    else
                    {
                        this.tbNoteInstrument[i] = (_parent2.tbNoteInstrument[i]);
                    }
                }
                for (int i = 8; i < 17; i++)
                {
                    //1 chance sur 5 de muté
                    if (rand.Next(0, 4) == 3)
                    {
                        this.tbNoteInstrument[i] = (_parent1.tbNoteInstrument[i] - 5 + rand.Next(0, 10));
                    }
                    else
                    {
                        this.tbNoteInstrument[i] = (_parent1.tbNoteInstrument[i]);
                    }
                }
            }
        }

        /// <summary>
        /// Create the MidiSong
        /// </summary>
        public void createMidiSong(int _nbFile)
        {
            string test = (Directory.GetCurrentDirectory() + "\\Fichier" + _nbFile + ".mid");          
            if (!File.Exists(test))
            {
                MIDISong song = new MIDISong();
                song.AddTrack("Piste" + _nbFile);
                song.SetTimeSignature(0, 4, 4);
                song.SetTempo(0, 150);
                song.SetChannelInstrument(0, 0, this.tbNoteInstrument[16]);

                for (int i = 0; i < 16; i++)
                {
                    song.AddNote(0, 0, this.tbNoteInstrument[i], 12);
                }



                MemoryStream ms = new MemoryStream();
                song.Save(ms);
                ms.Seek(0, SeekOrigin.Begin);
                this.src = ms.GetBuffer();
                this.dst = new byte[src.Length];
                for (int i = 0; i < src.Length; i++)
                {
                    this.dst[i] = this.src[i];
                }
                ms.Close();

                string strFileName = "Fichier" + _nbFile + ".mid";
                FileStream objWriter = File.Create(strFileName);
                objWriter.Write(dst, 0, dst.Length);
                objWriter.Close();
                objWriter.Dispose();
                objWriter = null;
            }
        }

        /// <summary>
        /// Play the MidiSong
        /// </summary>
        /// <param name="_nbIndividual">the number of the Individual</param>
        public void playMidiSong(int _nbIndividual)
        {          
            this.createMidiSong(_nbIndividual);         
            if (musicWindow.isPlaying)
            {
                musicWindow.mplayer.Stop();
                musicWindow.mplayer.Close();
                musicWindow.isPlaying = false;
            }
            musicWindow.mplayer.Open(new Uri("Fichier" + _nbIndividual + ".mid", UriKind.Relative));
            musicWindow.isPlaying = true;
            musicWindow.mplayer.Play();

        }

        /// <summary>
        /// Save the MidiSong in the explorer
        /// </summary>
        public void saveMidiSong()
        {
            SaveFileDialog saveFileDialog1 = new SaveFileDialog();
            saveFileDialog1.Filter = "MIDI song|*.mid";
            saveFileDialog1.Title = "Save a MIDI song";
            saveFileDialog1.ShowDialog();

            // If the file name is not an empty string open it for saving.
            if (saveFileDialog1.FileName != "")
            {

                switch (saveFileDialog1.FilterIndex)
                {
                    case 1:
                        FileStream objWriter = File.Create(saveFileDialog1.FileName);
                        objWriter.Write(this.dst, 0, this.dst.Length);
                        objWriter.Close();
                        objWriter.Dispose();
                        objWriter = null;
                        break;
                }
            }
        }

        /// <summary>
        /// Set the tickets of the individual
        /// </summary>
        /// 
        public void setTickets(int _nbTickets)
        {
            this.tickets = _nbTickets;
        }

        /// <summary>
        /// get the tickets
        /// </summary>
        /// <returns>the tickets of the individual</returns>
        public int getTickets()
        {
            return this.tickets;
        }
    }

}
